---
title: Render a letter or report
summary: Builds a report/letter's XML (if needed) and renders it to PDF bytes via clsPrint.
status: draft
owner: SAIF Case Management
last_reviewed: 2026-08-21
library: SAIF.Services.Printing
reference_type: embedded
operation_id: OP-REPORTING-RENDER
trigger: Caller invokes Reporting.ReportBase.Render, or it is invoked internally by Print/Save
---

# Render a letter or report

Renders a concrete report/letter subclass's XML document into PDF bytes, reusing a previously rendered file when possible.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-REPORTING-RENDER |
| **Trigger** | Caller invokes `Reporting.ReportBase.Render(overwrite)` directly, or it is invoked internally by [Print a letter or report](print-report.md) / [Save a rendered report to disk](save-report.md) |
| **Inputs** | `overwrite` flag |
| **Outputs** | Boolean success flag; populates `m_reportFile` with rendered PDF bytes |
| **Primary components** | `Reporting.ReportBase.Render`, `Reporting.ReportBase.Create` (overridable) |
| **Entry point** | `SAIF.Services.Printing\Reporting\ReportBase.vb` |

## Steps

1. Checks whether `m_reportFile` is already populated and `overwrite` is `False` — if so, short-circuits and returns `True` without re-rendering. (Note: clearing the internal error list happens in `Create`, not here.)
2. Otherwise calls `Create(overwrite)` — an overridable method; the concrete subclass (e.g., a specific letter type) builds the `Reporting.XDesignXDocument` tree, while the base implementation just clears the error list and returns the current, possibly-null, XML.
3. If the resulting `m_reportXml` is not `Nothing` and `ReportPackage` is non-empty:
   - Determines the security platform context: defaults to `clsSecurityPrincipal.Platform.Windows`, switched to `Platform.Web` if `_environmentService.IsWeb` is true (see [`IsWeb`](../configuration.md) configuration setting).
   - Constructs a `SAIF.Framework.Security.clsSecurityPrincipal` for that platform and calls `GetDefaultPrinter()` to set `xPrint.Printer`.
     > **Origin**: `GetDefaultPrinter()` is implemented in `SAIF.Framework.Security.clsSecurityPrincipal` (`SAIF.BOF.Framework.Security`, external package) and determines a default printer name based on platform and current principal.†
   - Calls `xPrint.previewDocument(m_ReportPackage, m_reportXml.ToXpression, OutputProfile)` — delegates into [Preview a document via xPression](preview-document-xpresso.md) — storing the returned PDF bytes in `m_reportFile`.
   - Sets `result = True`.
4. Any exception during the above is caught and recorded as an `ErrorDetail` in the `Errors` list.
   - On failure: the method returns `False` (implicit, since `result` was never set to `True` before the exception).

## Process flow

```mermaid
flowchart TD
	Start([Render called]) --> Cached{m_reportFile populated and overwrite=False?}
	Cached -->|Yes| EndOk([Return True, no re-render])
	Cached -->|No| CreateXml[Call Create - build XDesignXDocument]
	CreateXml --> Check{m_reportXml not Nothing and ReportPackage non-empty?}
	Check -->|No| EndFail([Return False])
	Check -->|Yes| Platform[Determine security platform via IsWeb]
	Platform --> Printer[GetDefaultPrinter via clsSecurityPrincipal]
	Printer --> Preview[Call xPrint.previewDocument]
	Preview --> EndOk2([Set result True, return True])
	Preview -->|Exception| Error[Record ErrorDetail, return False]
```

## Failure and edge-case behavior
- Exceptions during rendering are caught and recorded as an `ErrorDetail` in the `Errors` list rather than propagated to the caller.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `SAIF.Services.Printing\Reporting\ReportBase.vb`
